package com.firefly.admin.common.service;

import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.firefly.admin.common.constant.Constants;
import com.firefly.admin.common.entity.FyBatchOperationDetail;
import com.firefly.admin.common.entity.FyBatchOperationResult;
import com.firefly.admin.common.enums.ResultCodeEnum;
import com.firefly.admin.common.utils.DateUtil;
import com.firefly.admin.common.utils.ExcelImportUtil;
import com.firefly.admin.common.vo.Result;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@Component
@Slf4j
public abstract class AbstractBatchOperationService<T> {
    private static final String DATE_FORMAT = "yyyy/MM/dd";
    private static final String CUSTOM_BUCKET = "admin";
    private static final int SHEET_START = 0;
    private static final int ROW_START = 1;
    @Autowired
    private FtpService ftpService;
    @Autowired
    private FyBatchOperationResultService fyBatchOperationResultService;
    @Autowired
    private FyBatchOperationDetailService fyBatchOperationDetailService;

    public Result<FyBatchOperationResult<T>> batchImport(MultipartFile file, String module) throws IOException {
        boolean isExcelFile = ExcelImportUtil.isExcelFile(file);
        if (!isExcelFile) {
            log.info("batch operation file type error!!");
            return Result.getResult(ResultCodeEnum.BATCH_IMPORT_FILE_TYPE_ERROR);
        }
        String fileName = file.getOriginalFilename();
        String path = DateUtil.getNowDateString(DATE_FORMAT);
        String fileUrl = ftpService.upload(file, path, CUSTOM_BUCKET);
        log.info("batch operation fileName = [{}] ,filePath = [{}] !!", fileName, fileUrl);
        XSSFWorkbook workbook = new XSSFWorkbook(file.getInputStream());
        XSSFSheet sheet = workbook.getSheetAt(SHEET_START);
        if (sheet == null) {
            return Result.getResult(ResultCodeEnum.BATCH_IMPORT_FILE_IS_NULL);
        }
        int lastRowNum = sheet.getLastRowNum();
        if (lastRowNum <= ROW_START) {
            return Result.getResult(ResultCodeEnum.BATCH_IMPORT_FILE_IS_NULL);
        }
        FyBatchOperationResult<T> batchOperationResult = new FyBatchOperationResult<>();
        List<T> excelData = new ArrayList<>();
        boolean allVerifyResult = true;
        for (int i = ROW_START; i < lastRowNum; i++) {
            XSSFRow row = sheet.getRow(i);
            if (row == null) {
                continue;
            }
            FyBatchOperationDetail<T> batchOperationDetail = verifyRowData(row);
            if (batchOperationDetail == null) {
                allVerifyResult = false;
                batchOperationDetail = new FyBatchOperationDetail<>();
                batchOperationDetail.setVerifyResult(Constants.VerifyResult.FAIL);
                batchOperationDetail.setErrorMessage(ResultCodeEnum.BATCH_IMPORT_VERIFY_RESULT_IS_NULL.getMsg());
            } else if (Constants.VerifyResult.FAIL.equals(batchOperationDetail.getVerifyResult())) {
                allVerifyResult = false;
            }
            excelData.add(batchOperationDetail.getRowData());
            fyBatchOperationDetailService.save(batchOperationDetail);
        }
        batchOperationResult.setFileName(fileName);
        batchOperationResult.setFileNumber(IdWorker.getIdStr());
        batchOperationResult.setFilePath(fileUrl);
        batchOperationResult.setVerifyResult(allVerifyResult ? Constants.VerifyResult.SUCCESS : Constants.VerifyResult.FAIL);
        batchOperationResult.setModule(module);
        if (allVerifyResult) {
            //校验无错误直接提交
            for (T t : excelData) {
                save(t);
            }
            batchOperationResult.setSaveResult("1");
        }
        int row = fyBatchOperationResultService.save(batchOperationResult);
        if (row <= 0) {
            return Result.getResult(ResultCodeEnum.ADD_EXCEPTION);
        }
        return Result.success(batchOperationResult);
    }

    /**
     * 批量操作对象新增
     *
     * @param t 批量操作对象
     */
    public abstract void save(T t);

    /**
     * 批量操作行数据校验
     *
     * @param row 批量操作行数据
     * @return 校验结果
     */
    public abstract FyBatchOperationDetail<T> verifyRowData(XSSFRow row);

}
